﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;

namespace WcfContrib.Extensions.Behaviors
{
    /// <summary>
    /// A behavior that increases service endpoints max items in object graph to the maximum value and boosts the bindings.
    /// </summary>
    public class BoostedServiceBehaviorAttribute : Attribute, IServiceBehavior
    {
        bool addedBehaviors;
        const int DefaultMaxThrottleValue = 1000;

        /// <summary>
        /// Gets or sets the throttle value.
        /// </summary>
        /// <value>The throttle value.</value>
        public int ThrottleValue { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether to set throttling.
        /// </summary>
        /// <value><c>true</c> if to set throttling; otherwise, <c>false</c>.</value>
        public bool SetThrottling { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether to override configuration.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if to override configuration; otherwise, <c>false</c>.
        /// </value>
        public bool OverrideConfiguration { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoostedServiceBehaviorAttribute"/> class.
        /// </summary>
        public BoostedServiceBehaviorAttribute()
        {
            ThrottleValue = DefaultMaxThrottleValue;

            SetThrottling = true;
        }

        #region IServiceBehavior Members

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            if (!addedBehaviors)
            {
                addedBehaviors = true;

                foreach (var ep in serviceDescription.Endpoints)
                {
                    ep.Behaviors.Add(new BoostedEndpointBehaviorAttribute());
                }
            }
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            if (SetThrottling)
            {
                if (OverrideConfiguration)
                {
                    //remove if already exists
                    serviceDescription.Behaviors.Remove<ServiceThrottlingBehavior>();
                }

                if (OverrideConfiguration || serviceDescription.Behaviors.Find<ServiceThrottlingBehavior>() == null)
                {
                    ServiceThrottlingBehavior throttle = new ServiceThrottlingBehavior();
                    serviceDescription.Behaviors.Add(throttle);

                    throttle.MaxConcurrentCalls = ThrottleValue;
                    throttle.MaxConcurrentInstances = ThrottleValue;
                    throttle.MaxConcurrentSessions = ThrottleValue;
                }
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        #endregion
    }
}
